<template>
  <div class="app-container">
    <!-- 功能说明提示 -->
    <el-alert
      title="文件管理模块说明"
      type="info"
      description="本模块用于存储和管理医学图像及检查报告等相关文件。您可以上传、查看和下载患者的检查图像及相关文档。目前部分功能可能尚未实现，仅供演示使用。"
      show-icon
      :closable="false"
      style="margin-bottom: 20px"
    />

    <!-- 搜索和筛选区域 -->
    <el-card class="filter-container" shadow="never">
      <el-form :inline="true" :model="searchForm" ref="searchFormRef" size="small">
        <el-form-item label="文件名">
          <el-input v-model="searchForm.filename" placeholder="请输入文件名" clearable @keyup.enter="handleSearch" />
        </el-form-item>
        <el-form-item label="文件类型">
          <el-select v-model="searchForm.type" placeholder="请选择文件类型" clearable>
            <el-option label="图片" value="image" />
            <el-option label="文档" value="document" />
            <el-option label="视频" value="video" />
            <el-option label="音频" value="audio" />
            <el-option label="其他" value="other" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">搜索</el-button>
          <el-button @click="resetSearch">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 数据表格 -->
    <el-card shadow="never">
      <template #header>
        <div class="card-header">
          <h3>文件列表</h3>
          <div>
            <el-upload
              class="upload-button"
              :action="`${baseURL}/files/upload`"
              :headers="uploadHeaders"
              :on-success="handleUploadSuccess"
              :on-error="handleUploadError"
              :before-upload="beforeUpload"
              :show-file-list="false"
              multiple
            >
              <el-button 
                type="primary"
                v-permission="'file:create'"
              >
                上传文件
              </el-button>
            </el-upload>
          </div>
        </div>
      </template>

      <el-table
        v-loading="loading"
        :data="fileList"
        border
        style="width: 100%"
        row-key="id"
        @sort-change="handleSortChange"
      >
        <template #empty>
          <div class="empty-block">
            <el-empty description="暂无文件记录" :image-size="100">
              <template #description>
                <p>暂无文件记录，您可以点击上方"上传文件"按钮添加文件</p>
              </template>
              <el-button type="primary" @click="$el.querySelector('.el-upload__input').click()">
                上传文件
              </el-button>
            </el-empty>
          </div>
        </template>
        <el-table-column label="文件名" min-width="200">
          <template #default="scope">
            <div class="file-name">
              <el-icon class="file-icon">
                <component :is="getFileIcon(scope.row.contentType)" />
              </el-icon>
              <span>{{ scope.row.filename }}</span>
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="contentType" label="类型" min-width="120" />
        <el-table-column prop="size" label="大小" min-width="100">
          <template #default="scope">
            {{ formatFileSize(scope.row.size) }}
          </template>
        </el-table-column>
        <el-table-column prop="uploadByName" label="上传者" min-width="120" />
        <el-table-column prop="createdAt" label="上传时间" min-width="180" sortable="custom">
          <template #default="scope">
            {{ formatDateTime(scope.row.createdAt) }}
          </template>
        </el-table-column>
        <el-table-column label="操作" fixed="right" width="180">
          <template #default="scope">
            <el-button
              type="primary"
              link
              size="small"
              @click="handlePreview(scope.row)"
            >
              预览
            </el-button>
            <el-button
              type="success"
              link
              size="small"
              @click="handleDownload(scope.row)"
            >
              下载
            </el-button>
            <el-button
              type="danger"
              link
              size="small"
              @click="handleDelete(scope.row)"
              v-permission="'file:delete'"
            >
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <div class="pagination-container">
        <el-pagination
          background
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          v-model:current-page="page"
          v-model:page-size="limit"
          @size-change="fetchFiles"
          @current-change="fetchFiles"
        />
      </div>
    </el-card>

    <!-- 预览对话框 -->
    <el-dialog
      v-model="previewDialog.visible"
      :title="previewDialog.title"
      width="80%"
    >
      <div class="preview-container">
        <!-- 图片预览 -->
        <div v-if="previewDialog.type === 'image'" class="image-preview">
          <img :src="previewDialog.url" alt="预览图片" @error="handleImageError" />
          <div v-if="imageLoadError" class="error-message">
            图片加载失败，可能是格式不支持或数据损坏
          </div>
        </div>
        
        <!-- PDF预览 -->
        <div v-else-if="previewDialog.type === 'pdf'" class="pdf-preview">
          <iframe :src="previewDialog.url" frameborder="0" width="100%" height="600"></iframe>
        </div>
        
        <!-- 视频预览 -->
        <div v-else-if="previewDialog.type === 'video'" class="video-preview">
          <video :src="previewDialog.url" controls width="100%"></video>
        </div>
        
        <!-- 音频预览 -->
        <div v-else-if="previewDialog.type === 'audio'" class="audio-preview">
          <audio :src="previewDialog.url" controls style="width: 100%"></audio>
        </div>
        
        <!-- 其他类型，提供下载 -->
        <div v-else class="other-preview">
          <p>无法预览此类型的文件，请点击下载按钮下载后查看</p>
          <el-button type="primary" @click="handleDownload(previewDialog.file)">下载文件</el-button>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { fileAPI } from '@/utils/api'
import { formatDateTime } from '@/utils/format'
import { Document, Picture, VideoPlay, Headset, Files } from '@element-plus/icons-vue'

// 基础URL
const baseURL = '/api/v1'

// 数据列表
const fileList = ref([])
const loading = ref(false)
const total = ref(0)
const page = ref(1)
const limit = ref(20)
const sortBy = ref('createdAt')
const order = ref('desc')

// 搜索表单
const searchFormRef = ref(null)
const searchForm = reactive({
  filename: '',
  type: ''
})

// 预览对话框
const previewDialog = reactive({
  visible: false,
  title: '',
  url: '',
  type: '',
  file: null
})

// 图片加载错误状态
const imageLoadError = ref(false)

// 处理图片加载错误
const handleImageError = (event) => {
  console.error('图片加载失败:', event)
  imageLoadError.value = true
}

// 上传请求头
const uploadHeaders = computed(() => {
  const token = localStorage.getItem('token')
  return {
    Authorization: token ? `Bearer ${token}` : ''
  }
})

// 获取文件列表
const fetchFiles = async () => {
  loading.value = true;
  try {
    const params = {
      page: page.value,
      limit: limit.value,
      sortBy: sortBy.value,
      order: order.value,
      ...searchForm
    };
    
    console.log('正在请求文件列表API，参数:', params);
    
    const response = await fileAPI.getFiles(params);
    console.log('文件列表API完整响应:', response);
    
    // 检查response和response.data的格式
    if (response && response.data) {
      // 注意: API实际返回的是 {total, page, limit, files} 结构，不是嵌套在data里的
      console.log('API响应数据结构:', JSON.stringify(response.data));
      
      // 直接使用返回的数据结构
      if (response.success === true) {
        // 正确处理API返回的数据结构
        if (Array.isArray(response.data.files)) {
          // 数据格式正确
          fileList.value = response.data.files || [];
          total.value = response.data.total || 0;
          console.log('成功获取到文件列表，数量:', fileList.value.length);
          
          if (fileList.value.length === 0) {
            ElMessage.info('暂无文件记录');
          }
        } else {
          console.error('API返回的files字段不是数组:', response.data);
          ElMessage.error('获取文件列表失败：返回数据格式异常');
          fileList.value = [];
          total.value = 0;
        }
      } else {
        console.error('API返回失败:', response);
        ElMessage.error(response.message || '获取文件列表失败');
        fileList.value = [];
        total.value = 0;
      }
    } else {
      console.error('API响应格式不正确:', response);
      ElMessage.error('获取文件列表失败：响应格式不正确');
      fileList.value = [];
      total.value = 0;
    }
  } catch (error) {
    console.error('获取文件列表失败:', error);
    fileList.value = [];
    total.value = 0;
    
    // 添加更详细的错误信息
    if (error.response) {
      // 服务器返回了错误状态码
      console.error('服务器错误状态码:', error.response.status);
      console.error('服务器错误信息:', error.response.data);
      
      if (error.response.status === 404) {
        ElMessage.error('文件管理API路径不存在');
      } else if (error.response.status === 401) {
        ElMessage.error('未授权访问文件管理API，请检查登录状态和权限');
      } else if (error.response.status === 403) {
        ElMessage.error('无权限访问文件管理功能，请联系管理员');
      } else {
        ElMessage.error(`获取文件列表失败: 服务器返回 ${error.response.status} 错误`);
      }
    } else if (error.request) {
      // 请求已发送但没有收到响应
      console.error('未收到服务器响应:', error.request);
      ElMessage.error('获取文件列表失败: 未收到服务器响应，请检查网络连接');
    } else {
      // 请求设置时出错
      console.error('请求设置错误:', error.message);
      ElMessage.error(`获取文件列表失败: ${error.message}`);
    }
  } finally {
    loading.value = false;
  }
}

// 搜索
const handleSearch = () => {
  page.value = 1
  fetchFiles()
}

// 重置搜索
const resetSearch = () => {
  searchFormRef.value.resetFields()
  page.value = 1
  fetchFiles()
}

// 排序变化
const handleSortChange = (column) => {
  if (column.prop) {
    sortBy.value = column.prop
    order.value = column.order === 'ascending' ? 'asc' : 'desc'
    fetchFiles()
  }
}

// 格式化文件大小
const formatFileSize = (size) => {
  if (!size) return '0 B'
  
  const units = ['B', 'KB', 'MB', 'GB', 'TB']
  let i = 0
  while (size >= 1024 && i < units.length - 1) {
    size /= 1024
    i++
  }
  
  return `${size.toFixed(2)} ${units[i]}`
}

// 获取文件图标
const getFileIcon = (contentType) => {
  if (!contentType) return Files
  
  if (contentType.startsWith('image/')) {
    return Picture
  } else if (contentType.startsWith('video/')) {
    return VideoPlay
  } else if (contentType.startsWith('audio/')) {
    return Headset
  } else if (
    contentType === 'application/pdf' ||
    contentType === 'application/msword' ||
    contentType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ||
    contentType === 'text/plain'
  ) {
    return Document
  } else {
    return Files
  }
}

// 上传前检查
const beforeUpload = (file) => {
  // 文件大小限制为10MB
  const isLt10M = file.size / 1024 / 1024 < 10
  
  if (!isLt10M) {
    ElMessage.error('上传文件大小不能超过10MB')
    return false
  }
  
  return true
}

// 上传成功处理
const handleUploadSuccess = (response) => {
  if (response.success) {
    ElMessage.success('文件上传成功')
    fetchFiles()
  } else {
    ElMessage.error(response.message || '文件上传失败')
  }
}

// 上传失败处理
const handleUploadError = () => {
  ElMessage.error('文件上传失败')
}

// 预览文件
const handlePreview = async (row) => {
  console.log('预览文件:', row);
  
  // 重置图片错误状态
  imageLoadError.value = false;
  
  // 不同类型文件的预览处理
  let previewType = 'other';
  
  if (row.contentType.startsWith('image/')) {
    previewType = 'image';
  } else if (row.contentType === 'application/pdf') {
    previewType = 'pdf';
  } else if (row.contentType.startsWith('video/')) {
    previewType = 'video';
  } else if (row.contentType.startsWith('audio/')) {
    previewType = 'audio';
  }
  
  previewDialog.title = row.filename;
  previewDialog.type = previewType;
  previewDialog.file = row;
  
  try {
    // 获取token
    const token = localStorage.getItem('token');
    if (!token) {
      ElMessage.error('您未登录或登录已过期，请重新登录');
      return;
    }
    
    // 使用正确的数据API路径
    const fileUrl = `${baseURL}/files/data/${row.id}`;
    console.log('获取文件内容URL:', fileUrl);
    
    // 对于图片类型，先尝试获取文件内容
    if (previewType === 'image') {
      try {
        const response = await fileAPI.getFileData(row.id);
        console.log('获取到图片数据:', response);
        
        // 如果成功获取数据，使用返回的数据作为图片URL
        if (response.data) {
          previewDialog.url = response.data;
        } else {
          // 创建临时Blob URL
          const blob = await fetchWithAuth(fileUrl);
          previewDialog.url = URL.createObjectURL(blob);
        }
      } catch (error) {
        console.error('获取图片数据失败:', error);
        // 如果获取失败，回退到直接使用Blob URL
        const blob = await fetchWithAuth(fileUrl);
        previewDialog.url = URL.createObjectURL(blob);
      }
    } else if (previewType === 'pdf') {
      // 对于PDF，创建一个带认证的blob URL
      const blob = await fetchWithAuth(fileUrl);
      previewDialog.url = URL.createObjectURL(blob);
    } else if (previewType === 'video' || previewType === 'audio') {
      // 对于视频和音频，创建一个带认证的blob URL
      const blob = await fetchWithAuth(fileUrl);
      previewDialog.url = URL.createObjectURL(blob);
    } else {
      // 对于其他类型，还是存储API URL用于下载
      previewDialog.url = fileUrl;
    }
    
    previewDialog.visible = true;
  } catch (error) {
    console.error('预览文件失败', error);
    ElMessage.error('预览文件失败: ' + error.message);
  }
}

// 辅助函数：使用授权头获取文件内容并创建Blob
const fetchWithAuth = async (url) => {
  const token = localStorage.getItem('token');
  
  // 使用fetch API带上认证头
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });
  
  if (!response.ok) {
    throw new Error(`服务器返回错误: ${response.status}`);
  }
  
  // 获取内容类型
  const contentType = response.headers.get('content-type');
  console.log('响应内容类型:', contentType);
  
  // 获取响应数据
  const data = await response.text();
  
  // 检查是否是base64编码的数据URL
  if (data.startsWith('data:')) {
    console.log('检测到data URL格式数据');
    
    // 对于data URL格式，需要提取base64部分并解码
    try {
      // 提取base64部分 (移除 "data:image/jpeg;base64," 这样的前缀)
      const base64Data = data.split(',')[1];
      
      // 如果是图片，构造正确的二进制数据
      if (contentType && contentType.startsWith('text/plain') && data.includes('data:image')) {
        // 内容是data URL格式的图片
        const imgContentType = data.split(',')[0].split(':')[1].split(';')[0];
        console.log('检测到图片数据，MIME类型:', imgContentType);
        
        // 解码base64数据为二进制
        const binaryString = atob(base64Data);
        const bytes = new Uint8Array(binaryString.length);
        for (let i = 0; i < binaryString.length; i++) {
          bytes[i] = binaryString.charCodeAt(i);
        }
        
        // 创建blob对象
        return new Blob([bytes], { type: imgContentType });
      }
    } catch (error) {
      console.error('处理data URL格式失败:', error);
    }
  }
  
  // 处理常规二进制数据 (备用处理方法)
  return await response.blob();
};

// 下载文件
const handleDownload = async (row) => {
  console.log('下载文件:', row);
  
  try {
    // 获取token
    const token = localStorage.getItem('token');
    if (!token) {
      ElMessage.error('您未登录或登录已过期，请重新登录');
      return;
    }
    
    // 构建下载URL
    const downloadUrl = `${baseURL}/files/data/${row.id}?download=true`;
    console.log('文件下载URL:', downloadUrl);
    
    // 使用带授权的fetch下载文件
    const blob = await fetchWithAuth(downloadUrl);
    console.log('下载的Blob对象:', blob);
    
    // 创建临时URL并通过隐藏链接下载
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', row.filename);
    document.body.appendChild(link);
    link.click();
    
    // 清理
    setTimeout(() => {
      document.body.removeChild(link);
      URL.revokeObjectURL(url);
    }, 100);
    
    ElMessage.success('开始下载文件');
  } catch (error) {
    console.error('下载文件失败:', error);
    ElMessage.error('下载文件失败: ' + error.message);
  }
}

// 删除文件
const handleDelete = (row) => {
  ElMessageBox.confirm('确定要删除该文件吗？删除后将无法恢复！', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(async () => {
    try {
      const res = await fileAPI.deleteFile(row.id)
      
      if (res.data && res.data.success) {
        ElMessage.success('文件删除成功')
        fetchFiles()
      } else {
        ElMessage.error(res.data.message || '文件删除失败')
      }
    } catch (error) {
      console.error('文件删除失败', error)
      ElMessage.error('文件删除失败')
    }
  }).catch(() => {})
}

// 生命周期钩子
onMounted(() => {
  fetchFiles()
})
</script>

<style scoped>
.filter-container {
  margin-bottom: 20px;
}
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.pagination-container {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}
.file-name {
  display: flex;
  align-items: center;
  gap: 8px;
}
.file-icon {
  font-size: 20px;
}
.preview-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 200px;
}
.image-preview img {
  max-width: 100%;
}
.error-message {
  color: #f56c6c;
  margin-top: 10px;
  text-align: center;
  font-size: 14px;
}
.other-preview {
  text-align: center;
}
</style> 